/**
 * This file is for performing local tests. It will not be turned in.
 */

#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include <iostream>

#include "Reflector.hpp"
#include "Rotor.hpp"
#include "Control.hpp"

using namespace std;

void toUpperCase(char*);

int main(int argc, char **argv) 
{
	//check arguments
	if ((argc < 3 || argc > 4) || strlen(argv[1]) != 6) {
		cerr << "USAGE: " << argv[0] << " config message [crib]" << endl;
		cerr << "  config  ... The configuration of the Rotors and the initial setting" << endl;
		cerr << "                in this form: 123ABC" << endl;
		cerr << "  message ... The message to en/decrypt" << endl;
		cerr << "  crib    ... (optional) The crib to use when brute forceing. The config" << endl;
		cerr << "                option will have no effect but still has to be correct" << endl;
		return EXIT_FAILURE;
	}

	//prepare arguments
	toUpperCase(argv[1]);
	toUpperCase(argv[2]);
	if (argc == 4) {
		toUpperCase(argv[3]);
	}
	
	//create reflector and Rotors
	Reflector reflector;
	reflector.add('A', 'Y');
	reflector.add('B', 'R');
	reflector.add('C', 'U');
	reflector.add('D', 'H');
	reflector.add('E', 'Q');
	reflector.add('F', 'S');
	reflector.add('G', 'L');
	reflector.add('I', 'P');
	reflector.add('J', 'X');
	reflector.add('K', 'N');
	reflector.add('M', 'O');
	reflector.add('T', 'Z');
	reflector.add('V', 'W');

	std::string configs[] = {"BDFHJLCPRTXVZNYEIWGAKMUSQO",
	                         "AJDKSIRUXBLHWTMCQGZNPYFVOE",
	                         "EKMFLGDQVZNTOWYHXUSPAIBRCJ", };

	//initialize rotors
	int rotorIndex1 = argv[1][0] - '1';
	Rotor rotor1(configs[rotorIndex1], argv[1][3]);

	int rotorIndex2 = argv[1][1] - '1';
	Rotor rotor2(configs[rotorIndex2], argv[1][4]);

	int rotorIndex3 = argv[1][2] - '1';
	Rotor rotor3(configs[rotorIndex3], argv[1][5]);

	//if the user just wants to en/decrypt
	if (argc == 3) {
		cout << encodeDecode(std::string(argv[2]), rotor1, rotor2, rotor3, reflector) << endl;

		//if we should bruteforce
	} else {
		std::set<std::string> result = bruteForce(std::string(argv[2]), std::string(argv[3]), rotor1, rotor2, rotor3, reflector);
		std::set<std::string>::iterator it;
		for (it = result.begin(); it != result.end(); it++) {
			cout << *it << endl << endl;
		}
	}
}

void toUpperCase(char* str) {
	for (unsigned int i = 0; i < strlen(str); i++) {
		str[i] = toupper(str[i]);
	}
}

